import runtimeType from '../../sys/runtimeType';
import config from '../../sys/config';
import http from '../http';
import calldeal from '../calldeal';
import { showLoading } from '../prompt';

/**
 * 【异步方法】download资源下载
 * @description download资源下载，参数详情请查看配置文件focus.config.js
 * @param parameter 方法参数
 */
function download(parameter) {
    
    // ------------------------------------------------ 参数预处理
    // 获取当前运行环境
    let runType = runtimeType();
    // 获取配置文件中的download信息
    let config_file = config('get').network;
    // 合并 配置文件参数、主动传入参数
    let config_result = Object.assign({}, config_file, parameter);
    // 成品请求地址 = 请求地址头 + api地址
    if (config_result["openHttphead"] == true) { config_result["url"] = http('get') + config_result["url"]; }
    
    // ------------------------------------------------ 通用调用事件
    /** 成功/失败回调逻辑处理，参数：data_backC-要回调的数据 */
    function deal_callback(data_backC) {
        // 如果是请求成功
        if (data_backC.isSuccess == true) {
            // 全局的成功方法调用结果
            let result_fileSuccess = true;
            // 配置文件成功方法
            if (config_file && config_file.success) { result_fileSuccess = config_file.success(data_backC); }
            // 主动参数的失败方法
            if (result_fileSuccess===false && parameter && parameter.fail) { parameter.fail(data_backC); }
            // 主动参数的成功方法
            else if (parameter && parameter.success) { parameter.success(data_backC); }
        }
        // 如果是请求失败
        else {
            // 全局的失败方法调用结果
            let result_fileFail = true;
            // 配置文件失败方法
            if (config_file && config_file.fail) { result_fileFail = config_file.fail(data_backC); }
            // 主动参数的失败方法
            if (result_fileFail!==false && parameter && parameter.fail) { parameter.fail(data_backC); }
        }
    };
    /** 进度变化监听回调逻辑处理，参数：data_backC-要回调的数据 */
    function deal_progress(data_backC) {
        // 全局的进度监听方法调用结果
        let result_fileProgress = true;
        // 配置文件成功方法
        if (config_file && config_file.progress) { result_fileProgress = config_file.progress(data_backC); }
        // 主动参数的成功方法
        if (result_fileProgress!==false && parameter && parameter.progress) { parameter.progress(data_backC); }
    }

    // ------------------------------------------------ header请求头
    // 要传递请求头 编辑
    let req_header = {};
    // 1. 配置文件header加入到此数据
    if (config_file["header"]) { for (let key in config_file["header"]) { req_header[key] = config_file.header[key]; } }
    // 2. 主动传递参数的header覆盖到此数据
    if (config_result["header"]) { for (let key in config_result["header"]) { req_header[key] = config_result.header[key]; } }
    
    // ------------------------------------------------ 地址栏传输数据
    // 请求地址取出
    let str_url_api = config_result["url"];
    // 地址栏数据添加
    for (let key in config_result["pathData"]) { str_url_api += '/' + config_result.pathData[key]; }
    
    // ------------------------------------------------ 调用下载请求api
    // 如果是“非UNI”环境
    if (runType == 'NOT-UNI')
    {
        // 获取当前本地的域名
        let str_host_local = window.location.host;
        // 要下载文件的地址域名
        let obj_URL_download = new URL(str_url_api);
        // 下载文件名称
        let str_downName = '下载文件';
        // 从 pathname 中找出文件名称
        if (obj_URL_download.pathname) {
            // 按'/'符号进行切割
            let arr_path = obj_URL_download.pathname.split('/');
            // 取出最后的名称元素
            let str_last = arr_path[(arr_path.length - 1)];
            // 如果名称有效
            if (str_last) { str_downName = str_last; }
        }

        // 如果是同源文件下载
        if (str_host_local == obj_URL_download.host)
        {
            // 创建节点id
            let str_dom_id = '__focus_network__download_a__';
            // 创建一个a节点
            let dom_a = document.createElement("a");
            dom_a.setAttribute('id', str_dom_id); // 节点id赋值
            dom_a.setAttribute('href', str_url_api); // 文件下载地址赋值
            dom_a.setAttribute('download', str_downName); // 文件下载名称赋值
            dom_a.style.width = '0'; // 元素设置为不可见
            dom_a.style.height = '0';
            dom_a.style.display = 'block';
            dom_a.style.opacity = '0';
            // 将a标签dom对象添加到页面中
            document.body.appendChild(dom_a);
            // 触发点击事件
            dom_a.click();
            // 销毁a标签dom元素
            dom_a.parentNode.removeChild(dom_a);
        }

        // 非同源文件下载
        else {
            // 显示"下载中"提示弹框
            if (config_result["loadingText"] != null) { showLoading(config_result["loadingText"] + ' 0%'); }
            
            // 创建 XMLHttpRequest 对象
            let xhr = new XMLHttpRequest();
            // 初始化实例对象
            xhr.open("GET", str_url_api, true);
            // 请求头数据赋值
            for (let k in req_header) { xhr.setRequestHeader(k, req_header[k]); }
            // 指定请求超时时间
            xhr.timeout = config_result["timeout"];
            // 接收完服务器返回数据后，进行的数据类型处理方式
            xhr.responseType = 'blob';

            // 获取响应头公共方法
            let fun_getResponseHeader = () => {
                // 结果响应头
                let obj_resHeaders = {};
                // 获取响应头
                let str_resHeaders = xhr.getAllResponseHeaders();
                // 如果存在响应头
                if (str_resHeaders) {
                    // 将响应头转换为数组
                    var arr_resHeaders = str_resHeaders.trim().split(/[\r\n]+/);
                    // 循环响应头数组
                    arr_resHeaders.forEach((line) => {
                        // 按照冒号再分割
                        var parts = line.split(': ');
                        // 头的名称
                        var header = parts.shift();
                        // 头的值
                        var value = parts.join(': ');
                        // 将头添加到结果对象
                        obj_resHeaders[header] = value;
                    });
                }
                // 返回处理后的响应头
                return obj_resHeaders;
            };

            // 下载进度回调
            xhr.addEventListener('progress', (ev) => {
                // 检测是否真实处理
                if (ev.lengthComputable) {
                    // 此文件下载进度计算，百分比，如： 53.8
                    let num_progress_file = Math.floor(ev.loaded / ev.total * 1000) / 10;
                    // 传回给监听方法的数据
                    let backThis = {
                        percentage: num_progress_file, // 进度百分比
                        total: ev.total, // 要处理数据的总量
                        over: ev.loaded, // 已经处理完成的数据的量
                    };
                    // 进度显示框
                    if (config_result["loadingText"] != null) { showLoading(config_result["loadingText"] + ' ' + backThis.percentage + '%'); }
                    // 进度变化监听回调逻辑处理
                    deal_progress(backThis);
                }
            });
            // 请求超时监听
            xhr.addEventListener('timeout', () => {
                // 获取响应头
                let obj_resHeaders = fun_getResponseHeader();
                // 获取接口请求结果对象
                let data_back = calldeal(config_result, 0, obj_resHeaders, null, 'timeout');
                // 回调逻辑处理
                deal_callback(data_back);
            });
            // 请求失败监听
            xhr.addEventListener('error', () => {
                // 获取响应头
                let obj_resHeaders = fun_getResponseHeader();
                // 获取接口请求结果对象
                let data_back = calldeal(config_result, xhr.status, obj_resHeaders, xhr.response);
                // 回调逻辑处理
                deal_callback(data_back);
            });
            // 请求成功监听
            xhr.addEventListener('load', () => {
                // 获取响应头
                let obj_resHeaders = fun_getResponseHeader();
                // 将地址上的资源转化为同源URL对象
                let str_url_blob = window.URL.createObjectURL(xhr.response);
                // 如果同源对象转化成功
                if (str_url_blob) {
                    // 创建节点id
                    let str_dom_id = '__focus_network__download_a__';
                    // 创建一个a节点
                    let dom_a = document.createElement("a");
                    dom_a.setAttribute('id', str_dom_id); // 节点id赋值
                    dom_a.setAttribute('href', str_url_blob); // 文件下载地址赋值
                    dom_a.setAttribute('download', str_downName); // 文件下载名称赋值
                    dom_a.style.width = '0'; // 元素设置为不可见
                    dom_a.style.height = '0';
                    dom_a.style.display = 'block';
                    dom_a.style.opacity = '0';
                    // 将a标签dom对象添加到页面中
                    document.body.appendChild(dom_a);
                    // 触发点击事件
                    dom_a.click();
                    // 销毁a标签dom元素
                    dom_a.parentNode.removeChild(dom_a);

                    // 封装返回数据
                    let obj_back = { tempFilePath: str_url_blob };
                    // 获取接口请求结果对象
                    let data_back = calldeal(config_result, xhr.status, obj_resHeaders, obj_back);
                    // 回调逻辑处理
                    deal_callback(data_back);
                }
                // 如果转化失败
                else {
                    // 封装返回数据
                    let obj_back = { tempFilePath: str_url_blob, errMsg: '同源对象转化失败' };
                    // 获取接口请求结果对象
                    let data_back = calldeal(config_result, 417, obj_resHeaders, obj_back);
                    // 回调逻辑处理
                    deal_callback(data_back);
                }
            });
            
            // 发送请求
            xhr.send();
        }
    }
    // 如果是UNI环境
    else {
        // 显示"下载中"提示弹框
        if (config_result["loadingText"] != null) { showLoading(config_result["loadingText"] + ' 0%'); }
        
        // 官方发起下载api
        let downloadTask = uni.downloadFile({
            url: str_url_api,
            header: req_header,
            timeout: config_result["timeout"],
            fail: (resD) => {
                // 获取接口请求结果对象
                let data_back = calldeal(config_result, 0, {}, resD, 'unifail');
                // 回调逻辑处理
                deal_callback(data_back);
            },
            success: (resD) => {
                // 获取接口请求结果对象
                let data_back = calldeal(config_result, resD.statusCode, {}, resD);
                // 回调逻辑处理
                deal_callback(data_back);
            },
        });
        
        // 上传进度监听
        downloadTask.onProgressUpdate((TaskD) => {
            // 传回给监听方法的数据
            let backThis = {
                percentage: TaskD.progress, // 进度百分比
                total: TaskD.totalBytesExpectedToWrite, // 要处理数据的总量
                over: TaskD.totalBytesWritten, // 已经处理完成的数据的量
            };
            // 进度显示框
            if (config_result["loadingText"] != null) { showLoading(config_result["loadingText"] + ' ' + backThis.percentage + '%'); }
            // 进度变化监听回调逻辑处理
            deal_progress(backThis);
        });
    }
    
}

export default download;